import uvicorn
from fastapi import FastAPI, Request
import time
from fastapi.middleware.cors import CORSMiddleware
from tortoise.contrib.fastapi import register_tortoise
from fastapi import WebSocket, WebSocketDisconnect
from typing import List, Dict
from apscheduler.schedulers.background import BackgroundScheduler

from tool.sessing import TORTOISE_ORM

app = FastAPI()
# 2. 初始化APScheduler调度器（使用后台线程执行任务）
scheduler = BackgroundScheduler()

# 该方法会在fastapi启动时触发，内部通过传递进去的app对象，监听服务启动和终止事件
# 当检测到启动事件时，会初始化Tortoise对象，如果generate_schemas为True则还会进行数据库迁移
# 当检测到终止事件时，会关闭连接
register_tortoise(
    app,
    config=TORTOISE_ORM,
    # generate_schemas=True,  # 如果数据库为空，则自动生成对应表单，生产环境不要开
    # add_exception_handlers=True,  # 生产环境不要开，会泄露调试信息
)


# 定义允许跨域请求的来源列表
origins = [
    "http://localhost",
    "http://localhost:5173",
    # 可以添加更多允许的域名，如生产环境域名
    "https://yourproductiondomain.com"
]

# 添加 CORS 中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,  # 允许的来源列表
    allow_credentials=True,  # 允许携带凭证（如 cookies）
    allow_methods=["*"],  # 允许的 HTTP 方法，* 表示允许所有方法
    allow_headers=["*"],  # 允许的 HTTP 请求头，* 表示允许所有头
)


@app.get("/")
def read_root():
    return {"Hello": "World"}

import asyncio

loop = asyncio.get_event_loop()

# 存储所有活跃的 WebSocket 连接
active_connections: List[WebSocket] = []
# 存储客户端ID与连接的映射（可选，用于定向推送）
client_connections: Dict[str, WebSocket] = {}


# # 广播消息给所有连接的客户端
# async def broadcast(message: str):
#     for connection in active_connections:
#         await connection.send_text(message)
#

# 定向推送消息给指定客户端
async def send_to_client(client_id: str, message: str):
    if client_id in client_connections:
        print("发送")

        await client_connections[client_id].send_text(message)


@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: str):
    # 接受客户端连接
    await websocket.accept()
    # 存储连接
    active_connections.append(websocket)
    client_connections[client_id] = websocket
    print(f"客户端 {client_id} 已连接，当前连接数：{len(active_connections)}")
    try:
        while True:
            # 接收客户端发送的消息
            data = await websocket.receive_text()
            print(f"收到客户端 {client_id} 的消息：{data}")

            # 1. 回复当前客户端（单独回应）-
            await websocket.send_text(f"服务器已收到你的消息：{data}")


            # 2. 广播给所有客户端（可选）
            # await broadcast(f"客户端 {client_id} 说：{data}")

            # 3. 模拟服务器主动推送（5秒后推送一条消息）
            # await asyncio.sleep(5)
            # await websocket.send_text(f"服务器主动推送：你5秒前发送了「{data}」")

    except WebSocketDisconnect:
        # 客户端断开连时清理连接
        active_connections.remove(websocket)
        client_connections.pop(client_id, None)
        print(f"客户端 {client_id} 已断开，当前连接数：{len(active_connections)}")



import json


# 3. 定义定时任务函数（示例：打印当前时间）def print_current_time():
def print_current_time():
    # data={"name":'','code':'111'}
    # client_connections['123'].send_text(json.dumps(data))

    global client_connections, loop

    # print(client_connections)
    # print(client_connections.get('123'))

    if '123' in client_connections:
        asyncio.run_coroutine_threadsafe(
            client_connections['123'].send_text('absss'),
            loop
        )


    print(f"定时任务执行：当前时间")


def heavy_task():
    """示例：耗时任务（演示调度器的异步执行）"""
    print("开始执行耗时任务...")
    time.sleep(15)  # 模拟耗时操作
    print("耗时任务执行完成")


# 4. 向调度器添加任务（配置触发规则）
def add_jobs():
    # 任务1：每隔5秒执行一次（interval触发）
    scheduler.add_job(
        func=print_current_time,
        trigger="interval",  # 间隔触发
        seconds=3,  # 间隔5秒
        id="time_printer"  # 任务唯一ID（用于后续操作，如删除）
    )

    # 任务2：每天12:30执行（cron触发，类似Linux的crontab）
    # scheduler.add_job(
    #     func=heavy_task,
    #     trigger="cron",  # CRON表达式触发
    #     hour=12,
    #     minute=30,
    #     id="daily_task"
    # )

    # 任务3：在特定时间执行一次（date触发）
    # scheduler.add_job(
    #     func=print_current_time,
    #     trigger="date",  # 特定时间触发
    #     run_date=datetime(2025, 12, 31, 23, 59, 59),  # 2025年12月31日23:59:59
    #     id="specific_time_task"
    # )


# 5. 利用FastAPI生命周期事件管理调度器
@app.on_event("startup")
def startup_event():
    global loop
    # loop = asyncio.get_event_loop()

    add_jobs()
    scheduler.start()
    print("调度器已启动")


@app.on_event("shutdown")
def shutdown_event():
    """应用关闭时，关闭调度器"""
    scheduler.shutdown()
    print("调度器已关闭")


if __name__ == '__main__':
    uvicorn.run("wedSocket:app", host="127.0.0.1", port=8001, reload=True)